/*
 * @Author: AI Assistant
 * @Date: 2024-01-01 00:00:00
 * @Last Modified by: AI Assistant
 * @Last Modified time: 2024-01-01 00:00:00
 */

import { Browser, Page } from 'puppeteer';
const puppeteer = require('puppeteer');
import path from 'path';

// 我创建的页面

class MyPage {

    page!: Page;

    constructor(browser: Browser) {
        this.init(browser);
    }

    isInit = false;
    isBusy = false;
    data: any;
    targetUrl = 'https://www.3dkeshihua.com/taro_vite_react_mobx_node_express_sequelize/#/render3DGoods';

    async init(browser: Browser) {
        this.page = await browser.newPage();
        // 访问目标页面
        await this.page.goto(this.targetUrl);
        // 注入notifyPuppeteer 回调
        await this.page.exposeFunction('notifyPuppeteer', (data: string) => {
            console.log('页面通知:', data.length);
            this.data = data;
        });
        this.isInit = true;
    }

    //  renderScene 渲染3D场景并返回base64
    async renderScene(params: Record<string, any>) {
        this.isBusy = true;
        this.data = undefined;

        this.page.evaluate(async (params) => {
            (window as any).renderCanvas(params);
        }, params);

        while (this.data === undefined) {
            await new Promise(resolve => setTimeout(resolve, 100));
        }

        this.isBusy = false;
        return this.data;
    }

}



/**
 * Puppeteer管理器类 - 提供预创建的浏览器页面池，优化3D渲染性能
 */
class PuppeteerManage {

    constructor() {
        this.init();
    }

    isDev = process.env.NODE_ENV?.trim() === "development";
    isTest = process.env.NODE_ENV?.trim() === "test";
    isProd = process.env.NODE_ENV?.trim() === "production";

    private browser!: Browser;
    private pages: MyPage[] = [];

    // Chrome路径配置
    private chromePaths = [
        path.join(process.env.LOCALAPPDATA || '', 'Google\\Chrome\\Application\\chrome.exe'),
        'C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe',
        'C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe'
    ];

    // 找到存在的Chrome路径
    private executablePath = (() => {
        try {
            const fs = require('fs');
            for (const chromePath of this.chromePaths) {
                if (fs.existsSync(chromePath)) {
                    console.log(`找到Chrome浏览器: ${chromePath}`);
                    return chromePath;
                }
            }
            console.warn('未找到Chrome浏览器，将使用默认路径');
            return undefined;
        } catch (error) {
            console.error('查找Chrome路径失败:', error);
            return undefined;
        }
    })();

    /**
     * 初始化puppeteer管理实例
     */
    public async init() {

        try {
            this.browser = this.isDev ?
                await puppeteer.launch({
                    headless: "new",
                    args: [
                        '--disable-gpu',                    // 禁用GPU加速
                        '--disable-dev-shm-usage',          // 禁用/dev/shm使用，避免内存不足
                        '--disable-setuid-sandbox',         // 禁用setuid沙箱
                        '--disable-features=site-per-process', // 禁用站点隔离特性
                        '--enable-webgl',                   // 启用WebGL支持
                        '--no-sandbox',                     // 关闭沙箱模式
                    ],
                    defaultViewport: { width: 512, height: 512 },
                    executablePath: this.executablePath,
                    timeout: 60000 // 浏览器启动超时时间
                })
                :
                await puppeteer.launch({
                    headless: true,
                    args: [
                        '--disable-gpu',
                        '--disable-dev-shm-usage',
                        '--disable-setuid-sandbox',
                        '--no-first-run',
                        '--no-zygote',
                        '--no-sandbox'
                    ],
                    timeout: 60000 // 浏览器启动超时时间
                }).then((browser: any) => {
                    return browser;
                }).catch((err: any) => {
                    console.log('初始化Puppeteer失败:', err);
                });

        } catch (error) {
            console.log('初始化Puppeteer失败:', error);
        }

        if (!this.browser) {
            console.log('初始化Puppeteer失败，未创建浏览器实例');
            return
        }

        // 预创建4个MyPage对象
        const pagePromises = [];
        for (let i = 0; i < 4; i++) {
            const myPage = new MyPage(this.browser);
            pagePromises.push(myPage);
            this.pages.push(myPage);
        }
        // 等待所有页面初始化完成
        await Promise.all(pagePromises.map(p =>
            new Promise<void>(resolve => {
                const checkInit = async () => {
                    if (p.isInit) return resolve();
                    await new Promise(r => setTimeout(r, 100));
                    checkInit();
                };
                checkInit();
            })
        ));
        console.log(`成功初始化${this.pages.length}个页面实例`);
    }

    /**
     * 渲染3D场景并返回base64
     */
    public async renderScene(params: Record<string, any>): Promise<string> {
        // 等待直到有可用页面
        while (this.pages.length === 0) {
            await new Promise(resolve => setTimeout(resolve, 100));
        }

        // 从页面池中取出一个页面
        const myPage = this.pages.pop()!;

        try {
            // 调用页面的渲染方法
            const result = await myPage.renderScene(params);
            return result;
        } finally {
            // 无论成功失败，都将页面放回池中
            this.pages.push(myPage);
        }
    }


}

// 创建单例实例
const puppeteerManage = new PuppeteerManage();

export default puppeteerManage;